/*	--- 签名算法 --- 


我们使用'非对称加密算法'的时候，对于一个'公钥-私钥对'，

通常是用'公钥加密'，'私钥解密'。

-------------------------

如果使用私钥加密，公钥解密是否可行呢？实际上是完全可行的。

不过我们再仔细想一想，私钥是保密的，而公钥是公开的，用私钥加密，那相当于所有人都可以用公钥解密。这个加密有什么意义？

这个加密的意义在于，如果小明用自己的私钥加密了一条消息，比如小明喜欢小红，然后他公开了加密消息，由于任何人都可以用小明的公钥解密，从而使得任何人都可以确认小明喜欢小红这条消息肯定是小明发出的，其他人不能伪造这个消息，小明也不能抵赖这条消息不是自己写的。


因此，私钥加密得到的密文实际上就是数字签名，要验证这个签名是否正确，只能用'私钥持有者发布的公钥'进行 解密验证。 

使用数字签名的目的是为了确认'某个信息'确实是由'指定的某个发送方'所发送的，任何人都不可能伪造消息，并且，发送方也不能抵赖。


在实际应用的时候，'数字签名'实际上并不是针对'原始消息'，而是针对'原始消息的哈希Hash'进行签名，即：	

	signature = encrypt(privateKey, sha256(message))


对'数字签名'进行验证实际上就是用'公钥'解密:
	
	hash = decrypted(publicKey, signature)


然后把'解密后的hash'与'原始消息的hash'进行对比。


--------------------------

因为用户总是使用自己的'私钥'进行签名，所以，私钥就相当于用户身份。

而公钥用来给'外部'验证'用户身份'。


常用数字签名算法有：

	· MD5withRSA
	· SHA1withRSA
	· SHA256withRSA


它们实际上就是指定某种哈希算法进行RSA签名的方式。	*/
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.*;

public class Main {
	public static void main(String[] args) throws GeneralSecurityException {
		
		// 生成RSA公钥/私钥
		KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA");
		kpGen.initialize(1024);

		KeyPair kp = kpGen.generateKeyPair();

		PrivateKey sk = kp.getPrivate();
		PublicKey pk = kp.getPublic();


		// 待签名的消息
		byte[] message = "Hello, I am Bob !".getBytes(StandardCharsets.UTF_8);

		// 使用'私钥'签名'消息'
		Signature s = Signature.getInstance("SHA1withRSA");
		s.initSign(sk); // 初始签名
		s.update(message);

		byte[] signed = s.sign(); // '私钥'签名后的'Hash码''

		System.out.println(String.format("signature: %x", new BigInteger(1, signed)));


		// 使用'公钥'验证
		Signature v = Signature.getInstance("SHA1withRSA");
		v.initVerify(pk); // 初始验证
		v.update(message);

		boolean valid = v.verify(signed); // Signature.verify()
			// 使用Signature.initVerify(pk)的公钥,对'私钥'进行verify(验证)
			// return true/false

		System.out.println("valid? " + valid); 
	}
}



/*
使用其他公钥，或者验证签名的时候修改原始信息，都无法验证成功。

#	DSA签名

除了RSA可以签名外，还可以使用DSA算法进行签名。

DSA是Digital Signature Algorithm的缩写，它使用ElGamal数字签名算法。

DSA只能配合SHA使用，常用的算法有：

	SHA1withDSA
	SHA256withDSA
	SHA512withDSA


和RSA数字签名相比，DSA的优点是更快。

-----------------------

#	ECDSA签名

椭圆曲线签名算法ECDSA：Elliptic Curve Digital Signature Algorithm也是一种常用的签名算法.

它的特点是可以从私钥推出公钥。比特币的签名算法就采用了ECDSA算法，使用标准椭圆曲线secp256k1。BouncyCastle提供了ECDSA的完整实现。


---------------------------------------------*/





/*	---- 签名算法 の 小结 ---- 


数字签名就是用'发送方的私钥'对【原始数据】进行'签名'，只有用'发送方的公钥'才能通过'签名验证'。


数字签名用于：

	· 防止伪造；
	· 防止抵赖；
	· 检测篡改。

常用的数字签名算法包括：MD5withRSA／SHA1withRSA／SHA256withRSA／SHA1withDSA／SHA256withDSA／SHA512withDSA／ECDSA等。


*/












































